﻿using System;
using System.ComponentModel;
using PersonaLibrary.Data;

namespace PersonaLibrary.Search
{
    public class Filter : INotifyPropertyChanged
    {
        private Filter _subFilter;
        private string _name;
        private string _displayName;
        private Func<BaseEntity, bool> _filter;
        private readonly Type _filterType;

        public Filter(string filterName, Type filterType)
        {
            Name = filterName;
            _filterType = filterType;
        }

        public string DisplayName
        {
            set
            {
                _displayName = value;
                RisePropertyChanged("DisplayName");
            }
            get
            {
                return _displayName;
            }
        }

        public string Name
        {
            protected set
            {
                if (!string.IsNullOrEmpty(value))
                    _name = value;
                else
                    _name = GetType().Name;
                RisePropertyChanged("Name");
            }
            get
            {
                return _name;
            }
        }

        public Filter SubFilter
        {
            set
            {
                _subFilter = value;
                RisePropertyChanged("SubFilter");
                _subFilter.PropertyChanged += delegate { RisePropertyChanged("SubFilter"); };
            }
            get
            {
                return _subFilter;
            }
        }

        public Func<BaseEntity, bool> FuncFilter
        {
            set 
            { 
                _filter = value;
                RisePropertyChanged("Filter");
            }
            get { return _filter; }
        }

        public Func<BaseEntity, bool> ToFunc()
        {
            if (SubFilter != null)
                return delegate(BaseEntity e)
                           {
                               if (_filter.Invoke(e))
                                   return SubFilter.ToFunc().Invoke(e);
                               return false;
                           };

            return _filter;
        }

        public Filter ContainseFilter(string filterName)
        {
            if (Name == filterName)
                return this;
            if (SubFilter != null)
                return SubFilter.ContainseFilter(filterName);

            return null;
        }

        public void ChangeFilter(string filterName, Func<BaseEntity, bool> filter)
        {
            if (Name == filterName)
                FuncFilter = filter;
            if (SubFilter != null)
                SubFilter.ChangeFilter(filterName, filter);
        }

        public Type FilterType
        {
            get
            {
                return _filterType;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RisePropertyChanged(string name)
        {
            if(PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        public override string ToString()
        {
            return Name;
        }
    }
}
